#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

// #define ONE (1 << 0)
// #define TWO (1 << 1)
// #define THREE (1 << 2)
// #define FOUR (1 << 3)
// #define FIVE (1 << 4)


// // code 1  向目标中传递多个标准位
// void PrintTest(int flags)
// {
//     if(flags & ONE) printf("one\n");
//     if(flags & TWO) printf("two\n");
//     if(flags & THREE) printf("three\n");
//     if(flags & FOUR) printf("four\n");
//     if(flags & FIVE) printf("five\n");
// }

// int main()
// {
//     printf("================\n");
//     PrintTest(ONE);
//     printf("================\n");
//     PrintTest(TWO);
//     printf("================\n");
//     PrintTest(THREE);
//     printf("================\n");
//     PrintTest(ONE | THREE);
//     printf("================\n");
//     PrintTest(ONE | TWO | THREE);
//     printf("================\n");
//     PrintTest(ONE | TWO | THREE | FOUR);
//     printf("================\n");

//     return 0;
// }




int main1()
{
    umask(0);
    open("log.txt", O_WRONLY|O_CREAT, 0666);

    return 0;
}




int main2()
{
    // O_TRUNC 默认清空
    //int fd1 = open("log.txt", O_WRONLY| O_CREAT | O_TRUNC, 0666); 
    // O_APPEND 追加式写入
    int fd1 = open("log.txt", O_WRONLY| O_CREAT | O_APPEND, 0666); 
    int fd2 = open("log.txt", O_WRONLY| O_CREAT | O_APPEND, 0666); 
    int fd3 = open("log.txt", O_WRONLY| O_CREAT | O_APPEND, 0666); 
    int fd4 = open("log.txt", O_WRONLY| O_CREAT | O_APPEND, 0666); 
    
    if(fd1 < 0)
    {
        perror("open");
        return 1;
    }
    printf("fd1: %d\n", fd1);
    printf("fd2: %d\n", fd2);
    printf("fd3: %d\n", fd3);
    printf("fd4: %d\n", fd4);

    const char* message = "aaa";
    //write(fd1, message, strlen(message));

    close(fd1);
    return 0;
}


int main3()
{
    const char *message = "hello write\n";
    write(1, message, strlen(message)); // 默认提供的
}


int main4()
{
    char buffer[128];
    ssize_t s = read(0, buffer, sizeof(buffer));
    if(s > 0){
        buffer[s - 1] = 0; // 吞掉最后一个换行符
        printf("%s\n", buffer);
    }
    return 0;
}


int main5()
{
    int fd1 = open("log.txt", O_WRONLY| O_CREAT | O_APPEND, 0666); 
    const char* message = "aaa\n";
    write(fd1, message, strlen(message) + 1);

    close(fd1);
    return 0;
}



int main6()
{
    printf("stdin: %d\n", stdin->_fileno);
    printf("stdout: %d\n", stdout->_fileno);
    printf("stderr: %d\n", stderr->_fileno);
    // stdin、stdout、stderr、file* 必须用到文件描述符
    FILE* fp = fopen("log.txt", "w");
    printf("fp: %d\n", fp->_fileno);

    return 0;
}

// 由于在 OS 上只认文件描述符，因此任意文件操作在 C 语言上都是 对系统调用的封装


int main7()
{
    close(1);
    int fd1 = open("log1.txt", O_WRONLY| O_CREAT | O_APPEND, 0666); 
    int fd2 = open("log2.txt", O_WRONLY| O_CREAT | O_APPEND, 0666); 
    int fd3 = open("log3.txt", O_WRONLY| O_CREAT | O_APPEND, 0666); 
    int fd4 = open("log4.txt", O_WRONLY| O_CREAT | O_APPEND, 0666); 
    
    printf("fd1: %d\n", fd1);
    printf("fd2: %d\n", fd2);
    printf("fd3: %d\n", fd3);
    printf("fd4: %d\n", fd4);

    fflush(stdout);  // TODO

    close(fd1);
    close(fd2);
    close(fd3);
    close(fd4);
    return 0;
}

 
int main()
{
    close(1);
    int fd1 = open("log1.txt", O_WRONLY| O_CREAT | O_APPEND, 0666); 
    printf("printf, fd1: %d\n", fd1);
    fprintf(stdout, "fprintf fd: %d\n", fd1);
    //fflush(stdout);  // TODO
    //close(fd1);

    return 0;
}

int main9()
{
    int fd = open("log.txt", O_WRONLY| O_CREAT | O_APPEND, 0666); 
    
    dup2(fd, 1); // 1 已经指向我们的文件了，

    printf("hello fd: %d\n", fd);
    fprintf(stdout, "hello fd: %d\n", fd);
    fputs("hello world\n", stdout);

    const char*message = "hello fwrite\n";
    fwrite(message, 1, strlen(message), stdout);
    

    return 0;
}



int main10()
{
    // 输入重定向：需要文件存在可读
    int fd = open("log.txt", O_RDONLY);
    dup2(fd, 0); // 拿 fd 新输入地址来覆盖文件

    char buffer[2048];
    size_t s = read(0, buffer, sizeof(buffer));
    
    if(s > 0)
    {
        buffer[s - 1] = 0;
        printf("stdin redir: \n%s\n", buffer);
    }

    return 0;
}




int main11()
{
    struct stat st;
    int n = stat("log.txt", &st);
    if(n < 0) return 1;
    printf("file size: %lu\n", st.st_size);
    int fd = open("log.txt", O_RDONLY);
    if(fd < 0)
    {
        perror("open");
        return 1;
    }
    printf("fd: %d\n", fd);

    char* file_buffer = (char*)malloc(st.st_size + 1);
    n = read(fd, file_buffer, st.st_size);
    if(n > 0)
    {
        file_buffer[n] = '\0';
        printf("%s\n", file_buffer);
    }
    return 0;
}







